﻿using EntitiesLayer;
using StubDataAccessLayer;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DataAccessLayer;

namespace BusinessLayer
{
    public class CoupeManager
    {
        private static SqlManager manager = new SqlManager();

        #region Singleton
        private static CoupeManager instance;

        public static CoupeManager Manager
        {
            get
            {
                if (instance == null)
                    instance = new CoupeManager();
                return instance;
            }
        }
        #endregion

        #region Constructors

        private CoupeManager() { }

        #endregion

        #region Properties

        /// <summary>
        /// Coupes
        /// </summary>
        public IList<Coupe> Cups
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Cups; // Données de la base de données
                //return DalManager.GetInstance().Cups; // Données "Stubées"
            }
        }

        public IList<Equipe> Teams
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Teams;
                //return DalManager.GetInstance().Teams;
            }
        }

        public IList<Stade> Stadiums
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Stadiums;
                //return DalManager.GetInstance().Stadiums;
            }
        }

        public IList<Match> Matchs
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Matches;
                //return DalManager.GetInstance().Matches;
            }
        }

        public IList<Reservation> Reservations
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Reservations;
                //return DalManager.GetInstance().Reservations; 
            }
        }

        public IList<Spectateur> Spectateurs
        {
            get 
            {
                return DataAccessAbstraction.DataAccess.Spectateurs;
                //return DalManager.GetInstance().Spectateurs;
            }
        }

        public IList<Joueur> Joueurs
        {
            get
            {
                return DataAccessAbstraction.DataAccess.Players;
                //return DalManager.GetInstance().Spectateurs;
            }
        }

        #endregion

        #region Methods

        public List<Match> ReturnAllMatch(Coupe coupe)
        {
            DalManager manager = DalManager.GetInstance();
            List<Match> listMatch = manager.returnAllMatches().ToList();

            List<Match> liste = new List<Match>();

            liste.AddRange(listMatch.FindAll(m => m.CoupeID == coupe.ID).OrderBy(ma => ma.Date));

            return liste;
        }

        public List<Stade> ReturnAllStade(Coupe coupe)
        {
            DalManager manager = DalManager.GetInstance();
            List<Match> listeMatch = manager.returnAllMatches().ToList();
            List<Stade> listeStade = manager.returnAllStades().ToList();

            List<Stade> res = new List<Stade>();

            res.AddRange(listeStade.FindAll(s => listeMatch.Exists(m => m.Stade.ID == s.ID && m.CoupeID == coupe.ID)));
            
            return res;             
        }

        public List<Joueur> ReturnAllAttrapeurDomicile(Coupe coupe)
        {
            DalManager manager = DalManager.GetInstance();
            List<Match> listeMatch = manager.returnAllMatches().ToList();
            List<Joueur> listeJoueur = manager.returnAllJoueurs().ToList();
            List<Equipe> listeEquipe = manager.returnAllEquipes().ToList();

            List<Joueur> res = new List<Joueur>();

            res.AddRange(listeJoueur.FindAll(j => j.Poste == PosteJoueur.ATTRAPEUR && listeMatch.Exists(m => m.CoupeID == coupe.ID && m.EquipeDomicile.ListJoueur.Exists(jou => jou.ID == j.ID))));

            return new List<Joueur>(res.Distinct());
        }

        #endregion

        #region MAJ Equipes

        public Equipe AddTeam(Equipe equipe)
        {
            equipe.ID = Teams.Count > 0 ? Teams.Max(e => e.ID) + 1 : 1;
            Equipe equipeNew = equipe;
            manager.Insert(equipeNew, "EQUIPE");
            return equipeNew;
            //DalManager.GetInstance().Teams.Add(equipeNew);
        }

        /// <summary>
        /// Permet de supprimer l'équipe qui porte l'id passé en paramètre.
        /// </summary>
        /// <param name="IDTeam"> ID de l'équipe</param>
        public void DeleteTeam(int IDTeam)
        {
            manager.Delete(IDTeam, "EQUIPE");
            //Equipe equipe = DalManager.GetInstance().Teams.ToList().Find(t => t.Nom.Equals(name));
            //if (equipe != null)
            //{
            //    DalManager.GetInstance().Teams.Remove(equipe);
            //}
        }

        public void UpdateTeam(Equipe equipe)
        {
            manager.Update(equipe, "EQUIPE");
        }

        #endregion

        #region MAJ Stades

        public void DeleteStadium(int IDStade)
        {
            manager.Delete(IDStade, "STADE");
            //Stade stade = DalManager.GetInstance().Stadiums.ToList().Find(s => s.Nom.Equals(nomStade));
            //if (stade != null)
            //{
            //    DalManager.GetInstance().Stadiums.Remove(DalManager.GetInstance().Stadiums.Single(s => s.ID == stade.ID));
            //}
        }

        public Stade AddStadium(Stade stade)
        {
            stade.ID = Stadiums.Count > 0 ? Stadiums.Max(s => s.ID) + 1 : 1;
            Stade stadeNew = stade;
            manager.Insert(stadeNew, "STADE");
            return stadeNew;

            //DalManager.GetInstance().Stadiums.Add(stadeNew);
        }

        public void UpdateStadium(Stade stadeUpdate)
        {
            manager.Update(stadeUpdate, "STADE");
        }
        
        #endregion

        #region MAJ Coupes

        public Coupe AddCoupe(Coupe coupe)
        {
            coupe.ID = Cups.Count > 0 ? Cups.Max(c => c.ID) + 1 : 1;
            Coupe coupeNew = coupe;
            manager.Insert(coupeNew, "COUPE");
            return coupeNew;
        }

        public void UpdateCoupe(Coupe coupeUpdate)
        {
            manager.Update(coupeUpdate, "COUPE");
        }

        public void DeleteCoupe(int IDCoupe)
        {
            manager.Delete(IDCoupe, "COUPE");
        }

        #endregion

        #region MAJ Joueur

        public Joueur AddJoueur(Joueur joVm)
        {
            joVm.ID = Joueurs.Count > 0 ? Joueurs.Max(e => e.ID) + 1 : 1;
            Joueur joueurNew = joVm;
            manager.Insert(joueurNew, "PLAYER");
            return joueurNew;
        }

        public void UpdateJoueur(Joueur joueurUpdate)
        {
            manager.Update(joueurUpdate, "PLAYER");
        }

        public void DeleteJoueur(int IDJoueur)
        {
            manager.Delete(IDJoueur, "PLAYER");
        }
        

        #endregion

        #region MAJ Match
        public Match AddMatch(Match mVm)
        {
            mVm.ID = Matchs.Count > 0 ? Matchs.Max(e => e.ID) + 1 : 1;
            Match matchNew = mVm;
            manager.Insert(matchNew, "MATCH");
            return matchNew;
        }

        public void UpdateMatch(Match matchUpdate)
        {
            manager.Update(matchUpdate, "MATCH");
        }

        public void DeleteMatch(int IDMatch)
        {
            manager.Delete(IDMatch, "MATCH");
        }
        #endregion

        #region MAJ Reservation
        public Reservation AddReservation(Reservation rVm)
        {
            rVm.ID = Reservations.Count > 0 ? Reservations.Max(e => e.ID) + 1 : 1;
            Reservation reserNew = rVm;
            manager.Insert(reserNew, "RESERVATION");
            return reserNew;
        }

        public void UpdateReservation(Reservation reservationUpdate)
        {
            manager.Update(reservationUpdate, "RESERVATION");
        }

        public void DeleteReservation(int IDReser)
        {
            manager.Delete(IDReser, "RESERVATION");
        }
        #endregion
    }
}